package com.lgCore.nativeInvok;

import com.alibaba.fastjson.JSON;
import com.google.protobuf.ByteString;
import com.lgCore.client.NettyClientBootstrap;
import com.lgCore.client.factory.CommonRpcClientFactory;
import com.lgCore.common.RpcException;
import com.lgCore.protoModel.ProtoMsg;
import com.lgCore.util.ByteObjUtil;
import com.lgCore.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.UUID;
import java.util.concurrent.LinkedBlockingQueue;

/**
 *
 * rpc本地客户端调用处理中心,
 * 不在springmvc层进行调用
 * ligang 2020/10/10
 */
@Component
public class NativeRpcFactory implements BaseNativeRpcFactory{
    Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * rpc直接调用
     * @param className 类名称
     * @param methodName 方法名称
     * @param args 方法所需参数
     * @return
     * @throws Throwable
     */
    public Object invoke(String className,String methodName, Object[] args) throws Throwable {
        try {
            //查询zk地址
            String zkPath=null;
//            zkPath = CommonRpcClientFactory.getiCommonRpcClientService().getServerDataByZk(className);
            //检验ip是否能ping通，不然循环取5次
            for (int i = 0; i < 5; i++) {
                zkPath = CommonRpcClientFactory.getiCommonRpcClientService().getServerDataByZk(className);
                if(StringUtils.isNullOrEmpty(zkPath)){
                    //可能由于zk客户端还没打开，所以需要等待
                    Thread.sleep(300);
                    continue;
                }
                boolean pingIp = validatorPingIP(zkPath);
                if (pingIp) {
                    break;
                }
            }
            if (StringUtils.isNullOrEmpty(zkPath)) {
                throw new RpcException("没有可以连接的IP");
            }
            //查询netty服务 bootStrap
            NettyClientBootstrap nettyClientBootstrap = CommonRpcClientFactory.getiCommonRpcClientService().getServerBootStrap(zkPath);
//        Class<?>[] paramTypes = new Class[]{String.class};
            //执行业务方法
//            CommonRpcRequest commonRpcRequest = new CommonRpcRequest();
//            commonRpcRequest.setServiceName(className);
//            commonRpcRequest.setRequestId(UUID.randomUUID().toString());
//            commonRpcRequest.setMethodName(methodName);
////        commonRpcRequest.setArgTypes(paramTypes);
//            commonRpcRequest.setRequestObjects(args);
//            AskMsg askMsg = new AskMsg();
////            askMsg.setClientId(Constants.getClientId());
//            AskParams askParams = new AskParams();
//            askParams.setCommonRpcRequest(commonRpcRequest);
//            askMsg.setParams(askParams);
//            askMsg.setBusinessId(UUID.randomUUID().toString());





            //登录请求
            ProtoMsg.RpcRequest.Builder newRpcRequest= ProtoMsg.RpcRequest.newBuilder();
            newRpcRequest.setServiceName(className);
            newRpcRequest.setMethodName(methodName);

//            newRpcRequest.setRequestObjects(JSON.toJSONString(args));
            newRpcRequest.setRequestObjects(ByteString.copyFrom(ByteObjUtil.objToBytes(args)));
            ProtoMsg.Message.Builder sendMessage = ProtoMsg.Message.newBuilder();
            sendMessage.setRpcRequest(newRpcRequest);

            Object object = CommonRpcClientFactory.getiCommonRpcClientService().executeSendRequest(nettyClientBootstrap, sendMessage.build());
            return object;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RpcException("rpc 调用失败");
        }
    }

    /**
     * 校验ip是否能ping通
     *
     * @param zkPath
     * @return
     */
    public boolean validatorPingIP(String zkPath) {
        try {

            InetAddress address = InetAddress.getByName(zkPath.split(":")[0]);
            return address.isReachable(50);
        } catch (UnknownHostException e) {
            System.err.println("Unable to lookup web.mit.edu");
        } catch (IOException e) {
            System.err.println("Unable to reach web.mit.edu");
        }
        return false;
    }
}
